﻿// -----------------------------------------------------------------------
//    This file is part of TSGE.
//
//    TSGE is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 2 of the License, or
//    (at your option) any later version.
//
//    TSGE is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with TSGE.  If not, see <http://www.gnu.org/licenses/>.
// -----------------------------------------------------------------------

namespace tsge.Classes
{
    using System;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows.Media;
    using System.Xml.Serialization;

    /// <summary>
    /// ItemPrefix Class Implementation
    /// 
    ///     Inherits:
    ///         - ICloneable
    ///         - INotifyPropertyChanged
    /// </summary>
    [Serializable]
    public class ItemPrefix : ICloneable, INotifyPropertyChanged
    {
        /// <summary>
        /// Internal copy of the item prefix id.
        /// </summary>
        private Int32 m_vPrefixId;

        /// <summary>
        /// Internal copy of the item prefix name.
        /// </summary>
        private String m_vPrefixName;

        /// <summary>
        /// Public PropertyChanged event to register onto.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Default Constructor
        /// </summary>
        public ItemPrefix()
        {
        }

        /// <summary>
        /// Invokes the PropertyChanged event if one is set.
        /// </summary>
        /// <param name="propName">Name of the property being updated.</param>
        private void NotifyPropertyChanged(String propName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        /// <summary>
        /// Gets or sets this item prefixes id.
        /// </summary>
        [XmlAttribute("id")]
        public Int32 Id
        {
            get { return this.m_vPrefixId; }
            set { this.m_vPrefixId = value; this.NotifyPropertyChanged("Id"); }
        }

        /// <summary>
        /// Gets or sets this item prefixes name.
        /// </summary>
        [XmlAttribute("prefix")]
        public String Prefix
        {
            get { return this.m_vPrefixName; }
            set { this.m_vPrefixName = value; this.NotifyPropertyChanged("Prefix"); }
        }

        /// <summary>
        /// ToString Override
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.Prefix;
        }

        /// <summary>
        /// ICloneable Implementation
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }

    /// <summary>
    /// Item Class Implementation
    /// 
    ///     Inherits:
    ///         - ICloneable
    ///         - INotifyPropertyChanged
    /// </summary>
    [Serializable]
    public class Item : ICloneable, INotifyPropertyChanged
    {
        /// <summary>
        /// Internal copy of Terraria item class members.
        /// </summary>
        private Boolean m_vMech;
        private Boolean m_vWet;
        private Byte m_vWetCount;
        private Boolean m_vLavaWet;
        private Int32 m_vWidth;
        private Int32 m_vHeight;
        private Boolean m_vActive;
        private Int32 m_vNoGrabDelay;
        private Boolean m_vBeingGrabbed;
        private Int32 m_vSpawnTime;
        private Boolean m_vWornArmor;
        private Int32 m_vOwnIgnore = -1;
        private Int32 m_vOwnTime;
        private Int32 m_vKeepTime;
        private Int32 m_vType;
        private String m_vName;
        private Int32 m_vHoldStyle;
        private Int32 m_vUseStyle;
        private Boolean m_vChannel;
        private Boolean m_vAccessory;
        private Int32 m_vUseAnimation;
        private Int32 m_vUseTime;
        private Int32 m_vStack;
        private Int32 m_vMaxStack;
        private Int32 m_vPick;
        private Int32 m_vAxe;
        private Int32 m_vHammer;
        private Int32 m_vTileBoost;
        private Int32 m_vCreateTile = -1;
        private Int32 m_vCreateWall = -1;
        private Int32 m_vPlaceStyle;
        private Int32 m_vDamage;
        private Single m_vKnockBack;
        private Int32 m_vHealLife;
        private Int32 m_vHealMana;
        private Boolean m_vPotion;
        private Boolean m_vConsumable;
        private Boolean m_vAutoReuse;
        private Boolean m_vUseTurn;
        private Color m_vColor;
        private Int32 m_vAlpha;
        private Single m_vScale = 1f;
        private Int32 m_vUseSound;
        private Int32 m_vDefense;
        private Int32 m_vHeadSlot = -1;
        private Int32 m_vBodySlot = -1;
        private Int32 m_vLegSlot = -1;
        private String m_vToolTip;
        private String m_vToolTip2;
        private Int32 m_vOwner = 255;
        private Int32 m_vRare;
        private Int32 m_vShoot;
        private Single m_vShootSpeed;
        private Int32 m_vAmmo;
        private Int32 m_vUseAmmo;
        private Int32 m_vLifeRegen;
        private Int32 m_vManaIncrease;
        private Boolean m_vBuyOnce;
        private Int32 m_vMana;
        private Boolean m_vNoUseGraphic;
        private Boolean m_vNoMelee;
        private Int32 m_vRelease;
        private Int32 m_vValue;
        private Boolean m_vBuy;
        private Boolean m_vSocial;
        private Boolean m_vVanity;
        private Boolean m_vMaterial;
        private Boolean m_vNoWet;
        private Int32 m_vBuffType;
        private Int32 m_vBuffTime;
        private Int32 m_vNetID;
        private Int32 m_vCrit;
        private Byte m_vPrefix;
        private Boolean m_vMelee;
        private Boolean m_vMagic;
        private Boolean m_vRanged;
        private Int32 m_vReuseDelay;

        /// <summary>
        /// Custom Item Variables (Not part of Terraria Item class.)
        /// </summary>
        private Int32 m_vId = 0;
        private Uri m_vIcon = new Uri(String.Format(@"{0}\Data\Items\item_{1}.png", AppDomain.CurrentDomain.BaseDirectory, 0), UriKind.Absolute);
        private Int32 m_vCount = 0;

        /// <summary>
        /// Public PropertyChanged event to register onto.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Default Constructor
        /// </summary>
        public Item()
        {
        }

        /// <summary>
        /// Invokes the PropertyChanged event if one is set.
        /// </summary>
        /// <param name="propName">Name of the property being updated.</param>
        private void NotifyPropertyChanged(String propName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        /// <summary>
        /// Updates this item entry to the given item.
        /// </summary>
        /// <param name="nItemId"></param>
        public void SetItem(Int32 nItemId)
        {
            var item = (from items in Terraria.Instance.Items
                        where items.NetID == nItemId
                        select items).SingleOrDefault().Clone() as Item;

            this.Mech = item.Mech;
            this.Wet = item.Wet;
            this.WetCount = item.WetCount;
            this.LavaWet = item.LavaWet;
            this.Width = item.Width;
            this.Height = item.Height;
            this.Active = item.Active;
            this.NoGrabDelay = item.NoGrabDelay;
            this.BeingGrabbed = item.BeingGrabbed;
            this.SpawnTime = item.SpawnTime;
            this.WornArmor = item.WornArmor;
            this.OwnIgnore = item.OwnIgnore;
            this.OwnTime = item.OwnTime;
            this.KeepTime = item.KeepTime;
            this.Type = item.Type;
            this.Name = item.Name;
            this.HoldStyle = item.HoldStyle;
            this.UseStyle = item.UseStyle;
            this.Channel = item.Channel;
            this.Accessory = item.Accessory;
            this.UseAnimation = item.UseAnimation;
            this.UseTime = item.UseTime;
            this.Stack = item.Stack;
            this.MaxStack = item.MaxStack;
            this.Pick = item.Pick;
            this.Axe = item.Axe;
            this.Hammer = item.Hammer;
            this.TileBoost = item.TileBoost;
            this.CreateTile = item.CreateTile;
            this.CreateWall = item.CreateWall;
            this.PlaceStyle = item.PlaceStyle;
            this.Damage = item.Damage;
            this.KnockBack = item.KnockBack;
            this.HealLife = item.HealLife;
            this.HealMana = item.HealMana;
            this.Potion = item.Potion;
            this.Consumable = item.Consumable;
            this.AutoReuse = item.AutoReuse;
            this.UseTurn = item.UseTurn;
            this.Color = item.Color;
            this.Alpha = item.Alpha;
            this.Scale = item.Scale;
            this.UseSound = item.UseSound;
            this.Defense = item.Defense;
            this.HeadSlot = item.HeadSlot;
            this.BodySlot = item.BodySlot;
            this.LegSlot = item.LegSlot;
            this.ToolTip = item.ToolTip;
            this.ToolTip2 = item.ToolTip2;
            this.Owner = item.Owner;
            this.Rare = item.Rare;
            this.Shoot = item.Shoot;
            this.ShootSpeed = item.ShootSpeed;
            this.Ammo = item.Ammo;
            this.UseAmmo = item.UseAmmo;
            this.LifeRegen = item.LifeRegen;
            this.ManaIncrease = item.ManaIncrease;
            this.BuyOnce = item.BuyOnce;
            this.Mana = item.Mana;
            this.NoUseGraphic = item.NoUseGraphic;
            this.NoMelee = item.NoMelee;
            this.Release = item.Release;
            this.Value = item.Value;
            this.Buy = item.Buy;
            this.Social = item.Social;
            this.Vanity = item.Vanity;
            this.Material = item.Material;
            this.NoWet = item.NoWet;
            this.BuffType = item.BuffType;
            this.BuffTime = item.BuffTime;
            this.NetID = item.NetID;
            this.Crit = item.Crit;
            this.Prefix = item.Prefix;
            this.Melee = item.Melee;
            this.Magic = item.Magic;
            this.Ranged = item.Ranged;
            this.ReuseDelay = item.ReuseDelay;
        }

        /// <summary>
        /// Gets or sets the mech of this item.
        /// </summary>
        [XmlElement("mech")]
        public Boolean Mech
        {
            get { return this.m_vMech; }
            set { this.m_vMech = value; this.NotifyPropertyChanged("Mech"); }
        }

        /// <summary>
        /// Gets or sets the wet of this item.
        /// </summary>
        [XmlElement("wet")]
        public Boolean Wet
        {
            get { return this.m_vWet; }
            set { this.m_vWet = value; this.NotifyPropertyChanged("Wet"); }
        }

        /// <summary>
        /// Gets or sets the wet count of this item.
        /// </summary>
        [XmlElement("wetCount")]
        public Byte WetCount
        {
            get { return this.m_vWetCount; }
            set { this.m_vWetCount = value; this.NotifyPropertyChanged("WetCount"); }
        }

        /// <summary>
        /// Gets or sets the lava wet of this item.
        /// </summary>
        [XmlElement("lavaWet")]
        public Boolean LavaWet
        {
            get { return this.m_vLavaWet; }
            set { this.m_vLavaWet = value; this.NotifyPropertyChanged("LavaWet"); }
        }

        /// <summary>
        /// Gets or sets the width of this item.
        /// </summary>
        [XmlElement("width")]
        public Int32 Width
        {
            get { return this.m_vWidth; }
            set { this.m_vWidth = value; this.NotifyPropertyChanged("Width"); }
        }

        /// <summary>
        /// Gets or sets the height of this item.
        /// </summary>
        [XmlElement("height")]
        public Int32 Height
        {
            get { return this.m_vHeight; }
            set { this.m_vHeight = value; this.NotifyPropertyChanged("Height"); }
        }

        /// <summary>
        /// Gets or sets the active state of this item.
        /// </summary>
        [XmlElement("active")]
        public Boolean Active
        {
            get { return this.m_vActive; }
            set { this.m_vActive = value; this.NotifyPropertyChanged("Active"); }
        }

        /// <summary>
        /// Gets or sets the no grab delay of this item.
        /// </summary>
        [XmlElement("noGrabDelay")]
        public Int32 NoGrabDelay
        {
            get { return this.m_vNoGrabDelay; }
            set { this.m_vNoGrabDelay = value; this.NotifyPropertyChanged("NoGrabDelay"); }
        }

        /// <summary>
        /// Gets or sets the being grabbed state of this item.
        /// </summary>
        [XmlElement("beingGrabbed")]
        public Boolean BeingGrabbed
        {
            get { return this.m_vBeingGrabbed; }
            set { this.m_vBeingGrabbed = value; this.NotifyPropertyChanged("BeingGrabbed"); }
        }

        /// <summary>
        /// Gets or sets the spawn time of this item.
        /// </summary>
        [XmlElement("spawnTime")]
        public Int32 SpawnTime
        {
            get { return this.m_vSpawnTime; }
            set { this.m_vSpawnTime = value; this.NotifyPropertyChanged("SpawnTime"); }
        }

        /// <summary>
        /// Gets or sets the worm armor flag of this item.
        /// </summary>
        [XmlElement("wornArmor")]
        public Boolean WornArmor
        {
            get { return this.m_vWornArmor; }
            set { this.m_vWornArmor = value; this.NotifyPropertyChanged("WornArmor"); }
        }

        /// <summary>
        /// Gets or sets the own ignore of this item.
        /// </summary>
        [XmlElement("ownIgnore")]
        public Int32 OwnIgnore
        {
            get { return this.m_vOwnIgnore; }
            set { this.m_vOwnIgnore = value; this.NotifyPropertyChanged("OwnIgnore"); }
        }

        /// <summary>
        /// Gets or sets the own time of this item.
        /// </summary>
        [XmlElement("ownTime")]
        public Int32 OwnTime
        {
            get { return this.m_vOwnTime; }
            set { this.m_vOwnTime = value; this.NotifyPropertyChanged("OwnTime"); }
        }

        /// <summary>
        /// Gets or sets the keep time of this item.
        /// </summary>
        [XmlElement("keepTime")]
        public Int32 KeepTime
        {
            get { return this.m_vKeepTime; }
            set { this.m_vKeepTime = value; this.NotifyPropertyChanged("KeepTime"); }
        }

        /// <summary>
        /// Gets or sets the type of this item.
        /// </summary>
        [XmlElement("type")]
        public Int32 Type
        {
            get { return this.m_vType; }
            set
            {
                this.m_vType = value;
                this.Id = value;
                
                this.NotifyPropertyChanged("Type");
            }
        }

        /// <summary>
        /// Gets or sets the name of this item.
        /// </summary>
        [XmlElement("name")]
        public String Name
        {
            get { return this.m_vName; }
            set { this.m_vName = value; this.NotifyPropertyChanged("Name"); }
        }

        /// <summary>
        /// Gets or sets the hold style of this item.
        /// </summary>
        [XmlElement("holdStyle")]
        public Int32 HoldStyle
        {
            get { return this.m_vHoldStyle; }
            set { this.m_vHoldStyle = value; this.NotifyPropertyChanged("HoldStyle"); }
        }

        /// <summary>
        /// Gets or sets the use style of this item.
        /// </summary>
        [XmlElement("useStyle")]
        public Int32 UseStyle
        {
            get { return this.m_vUseStyle; }
            set { this.m_vUseStyle = value; this.NotifyPropertyChanged("UseStyle"); }
        }

        /// <summary>
        /// Gets or sets the channel of this item.
        /// </summary>
        [XmlElement("channel")]
        public Boolean Channel
        {
            get { return this.m_vChannel; }
            set { this.m_vChannel = value; this.NotifyPropertyChanged("Channel"); }
        }

        /// <summary>
        /// Gets or sets the accessory flag of this item.
        /// </summary>
        [XmlElement("accessory")]
        public Boolean Accessory
        {
            get { return this.m_vAccessory; }
            set { this.m_vAccessory = value; this.NotifyPropertyChanged("Accessory"); }
        }

        /// <summary>
        /// Gets or sets the use animation of this item.
        /// </summary>
        [XmlElement("useAnimation")]
        public Int32 UseAnimation
        {
            get { return this.m_vUseAnimation; }
            set { this.m_vUseAnimation = value; this.NotifyPropertyChanged("UseAnimation"); }
        }

        /// <summary>
        /// Gets or sets the use time of this item.
        /// </summary>
        [XmlElement("useTime")]
        public Int32 UseTime
        {
            get { return this.m_vUseTime; }
            set { this.m_vUseTime = value; this.NotifyPropertyChanged("UseTime"); }
        }

        /// <summary>
        /// Gets or sets the stack of this item.
        /// </summary>
        [XmlElement("stack")]
        public Int32 Stack
        {
            get { return this.m_vStack; }
            set { this.m_vStack = value; this.NotifyPropertyChanged("Stack"); }
        }

        /// <summary>
        /// Gets or sets the max stack of this item.
        /// </summary>
        [XmlElement("maxStack")]
        public Int32 MaxStack
        {
            get { return this.m_vMaxStack; }
            set { this.m_vMaxStack = value; this.NotifyPropertyChanged("MaxStack"); }
        }

        /// <summary>
        /// Gets or sets the pick of this item.
        /// </summary>
        [XmlElement("pick")]
        public Int32 Pick
        {
            get { return this.m_vPick; }
            set { this.m_vPick = value; this.NotifyPropertyChanged("Pick"); }
        }
        
        /// <summary>
        /// Gets or sets the axe of this item.
        /// </summary>
        [XmlElement("axe")]
        public Int32 Axe
        {
            get { return this.m_vAxe; }
            set { this.m_vAxe = value; this.NotifyPropertyChanged("Axe"); }
        }

        /// <summary>
        /// Gets or sets the hammer of this item.
        /// </summary>
        [XmlElement("hammer")]
        public Int32 Hammer
        {
            get { return this.m_vHammer; }
            set { this.m_vHammer = value; this.NotifyPropertyChanged("Hammer"); }
        }

        /// <summary>
        /// Gets or sets the tile boost of this item.
        /// </summary>
        [XmlElement("tileBoost")]
        public Int32 TileBoost
        {
            get { return this.m_vTileBoost; }
            set { this.m_vTileBoost = value; this.NotifyPropertyChanged("TileBoost"); }
        }

        /// <summary>
        /// Gets or sets the create tile of this item.
        /// </summary>
        [XmlElement("createTile")]
        public Int32 CreateTile
        {
            get { return this.m_vCreateTile; }
            set { this.m_vCreateTile = value; this.NotifyPropertyChanged("CreateTile"); }
        }

        /// <summary>
        /// Gets or sets the create wall of this item.
        /// </summary>
        [XmlElement("createWall")]
        public Int32 CreateWall
        {
            get { return this.m_vCreateWall; }
            set { this.m_vCreateWall = value; this.NotifyPropertyChanged("CreateWall"); }
        }

        /// <summary>
        /// Gets or sets the place style of this item.
        /// </summary>
        [XmlElement("placeStyle")]
        public Int32 PlaceStyle
        {
            get { return this.m_vPlaceStyle; }
            set { this.m_vPlaceStyle = value; this.NotifyPropertyChanged("PlaceStyle"); }
        }

        /// <summary>
        /// Gets or sets the damage of this item.
        /// </summary>
        [XmlElement("damage")]
        public Int32 Damage
        {
            get { return this.m_vDamage; }
            set { this.m_vDamage = value; this.NotifyPropertyChanged("Damage"); }
        }

        /// <summary>
        /// Gets or sets the knock back of this item.
        /// </summary>
        [XmlElement("knockBack")]
        public Single KnockBack
        {
            get { return this.m_vKnockBack; }
            set { this.m_vKnockBack = value; this.NotifyPropertyChanged("KnockBack"); }
        }

        /// <summary>
        /// Gets or sets the heal life of this item.
        /// </summary>
        [XmlElement("healLife")]
        public Int32 HealLife
        {
            get { return this.m_vHealLife; }
            set { this.m_vHealLife = value; this.NotifyPropertyChanged("HealLife"); }
        }

        /// <summary>
        /// Gets or sets the heal mana of this item.
        /// </summary>
        [XmlElement("healMana")]
        public Int32 HealMana
        {
            get { return this.m_vHealMana; }
            set { this.m_vHealMana = value; this.NotifyPropertyChanged("HealMana"); }
        }

        /// <summary>
        /// Gets or sets the potion flag of this item.
        /// </summary>
        [XmlElement("potion")]
        public Boolean Potion
        {
            get { return this.m_vPotion; }
            set { this.m_vPotion = value; this.NotifyPropertyChanged("Potion"); }
        }

        /// <summary>
        /// Gets or sets the consumable flag of this item.
        /// </summary>
        [XmlElement("consumable")]
        public Boolean Consumable
        {
            get { return this.m_vConsumable; }
            set { this.m_vConsumable = value; this.NotifyPropertyChanged("Consumable"); }
        }

        /// <summary>
        /// Gets or sets the auto reuse flag of this item.
        /// </summary>
        [XmlElement("autoReuse")]
        public Boolean AutoReuse
        {
            get { return this.m_vAutoReuse; }
            set { this.m_vAutoReuse = value; this.NotifyPropertyChanged("AutoReuse"); }
        }

        /// <summary>
        /// Gets or sets the use turn flag of this item.
        /// </summary>
        [XmlElement("useTurn")]
        public Boolean UseTurn
        {
            get { return this.m_vUseTurn; }
            set { this.m_vUseTurn = value; this.NotifyPropertyChanged("UseTurn"); }
        }
        [XmlElement("color")]
        public Color Color
        {
            get { return this.m_vColor; }
            set { this.m_vColor = value; this.NotifyPropertyChanged("Color"); }
        }

        /// <summary>
        /// Gets or sets the alpha of this item.
        /// </summary>
        [XmlElement("alpha")]
        public Int32 Alpha
        {
            get { return this.m_vAlpha; }
            set { this.m_vAlpha = value; this.NotifyPropertyChanged("Alpha"); }
        }

        /// <summary>
        /// Gets or sets the scale of this item.
        /// </summary>
        [XmlElement("scale")]
        public Single Scale
        {
            get { return this.m_vScale; }
            set { this.m_vScale = value; this.NotifyPropertyChanged("Scale"); }
        }

        /// <summary>
        /// Gets or sets the use sound of this item.
        /// </summary>
        [XmlElement("useSound")]
        public Int32 UseSound
        {
            get { return this.m_vUseSound; }
            set { this.m_vUseSound = value; this.NotifyPropertyChanged("UseSound"); }
        }

        /// <summary>
        /// Gets or sets the defense of this item.
        /// </summary>
        [XmlElement("defense")]
        public Int32 Defense
        {
            get { return this.m_vDefense; }
            set { this.m_vDefense = value; this.NotifyPropertyChanged("Defense"); }
        }

        /// <summary>
        /// Gets orsets the head slot of this item.
        /// </summary>
        [XmlElement("headSlot")]
        public Int32 HeadSlot
        {
            get { return this.m_vHeadSlot; }
            set { this.m_vHeadSlot = value; this.NotifyPropertyChanged("HeadSlot"); }
        }

        /// <summary>
        /// Gets or sets the body slot of this item.
        /// </summary>
        [XmlElement("bodySlot")]
        public Int32 BodySlot
        {
            get { return this.m_vBodySlot; }
            set { this.m_vBodySlot = value; this.NotifyPropertyChanged("BodySlot"); }
        }

        /// <summary>
        /// Gets or sets the leg slot of this item.
        /// </summary>
        [XmlElement("legSlot")]
        public Int32 LegSlot
        {
            get { return this.m_vLegSlot; }
            set { this.m_vLegSlot = value; this.NotifyPropertyChanged("LegSlot"); }
        }

        /// <summary>
        /// Gets or sets the tooltip of this item.
        /// </summary>
        [XmlElement("toolTip")]
        public String ToolTip
        {
            get { return this.m_vToolTip; }
            set { this.m_vToolTip = value; this.NotifyPropertyChanged("ToolTip"); }
        }

        /// <summary>
        /// Gets or sets the tooltip2 of this item.
        /// </summary>
        [XmlElement("toolTip2")]
        public String ToolTip2
        {
            get { return this.m_vToolTip2; }
            set { this.m_vToolTip2 = value; this.NotifyPropertyChanged("ToolTip2"); }
        }

        /// <summary>
        /// Gets or sets the owner of this item.
        /// </summary>
        [XmlElement("owner")]
        public Int32 Owner
        {
            get { return this.m_vOwner; }
            set { this.m_vOwner = value; this.NotifyPropertyChanged("Owner"); }
        }

        /// <summary>
        /// Gets or sets the rare of this item.
        /// </summary>
        [XmlElement("rare")]
        public Int32 Rare
        {
            get { return this.m_vRare; }
            set { this.m_vRare = value; this.NotifyPropertyChanged("Rare"); }
        }

        /// <summary>
        /// Gets or sets the shoot of this item.
        /// </summary>
        [XmlElement("shoot")]
        public Int32 Shoot
        {
            get { return this.m_vShoot; }
            set { this.m_vShoot = value; this.NotifyPropertyChanged("Shoot"); }
        }

        /// <summary>
        /// Gets or sets the shoot speed of this item.
        /// </summary>
        [XmlElement("shootSpeed")]
        public Single ShootSpeed
        {
            get { return this.m_vShootSpeed; }
            set { this.m_vShootSpeed = value; this.NotifyPropertyChanged("ShootSpeed"); }
        }

        /// <summary>
        /// Gets or sets the ammo of this item.
        /// </summary>
        [XmlElement("ammo")]
        public Int32 Ammo
        {
            get { return this.m_vAmmo; }
            set { this.m_vAmmo = value; this.NotifyPropertyChanged("Ammo"); }
        }

        /// <summary>
        /// Gets or sets the use ammo of this item.
        /// </summary>
        [XmlElement("useAmmo")]
        public Int32 UseAmmo
        {
            get { return this.m_vUseAmmo; }
            set { this.m_vUseAmmo = value; this.NotifyPropertyChanged("UseAmmo"); }
        }

        /// <summary>
        /// Gets or sets the life regen of this item.
        /// </summary>
        [XmlElement("lifeRegen")]
        public Int32 LifeRegen
        {
            get { return this.m_vLifeRegen; }
            set { this.m_vLifeRegen = value; this.NotifyPropertyChanged("LifeRegen"); }
        }

        /// <summary>
        /// Gets or sets the mana increase of this item.
        /// </summary>
        [XmlElement("manaIncrease")]
        public Int32 ManaIncrease
        {
            get { return this.m_vManaIncrease; }
            set { this.m_vManaIncrease = value; this.NotifyPropertyChanged("ManaIncrease"); }
        }

        /// <summary>
        /// Gets or sets the buy once flag of this item.
        /// </summary>
        [XmlElement("buyOnce")]
        public Boolean BuyOnce
        {
            get { return this.m_vBuyOnce; }
            set { this.m_vBuyOnce = value; this.NotifyPropertyChanged("BuyOnce"); }
        }

        /// <summary>
        /// Gets or sets the mana of this item.
        /// </summary>
        [XmlElement("mana")]
        public Int32 Mana
        {
            get { return this.m_vMana; }
            set { this.m_vMana = value; this.NotifyPropertyChanged("Mana"); }
        }

        /// <summary>
        /// Gets or sets the no use graphic flag of this item.
        /// </summary>
        [XmlElement("noUseGraphic")]
        public Boolean NoUseGraphic
        {
            get { return this.m_vNoUseGraphic; }
            set { this.m_vNoUseGraphic = value; this.NotifyPropertyChanged("NoUseGraphic"); }
        }

        /// <summary>
        /// Gets or sets the no melee flag of this item.
        /// </summary>
        [XmlElement("noMelee")]
        public Boolean NoMelee
        {
            get { return this.m_vNoMelee; }
            set { this.m_vNoMelee = value; this.NotifyPropertyChanged("NoMelee"); }
        }

        /// <summary>
        /// Gets or sets the release of this item.
        /// </summary>
        [XmlElement("release")]
        public Int32 Release
        {
            get { return this.m_vRelease; }
            set { this.m_vRelease = value; this.NotifyPropertyChanged("Release"); }
        }

        /// <summary>
        /// Gets or sets the value of this item.
        /// </summary>
        [XmlElement("value")]
        public Int32 Value
        {
            get { return this.m_vValue; }
            set { this.m_vValue = value; this.NotifyPropertyChanged("Value"); }
        }

        /// <summary>
        /// Gets or sets the buy of this item.
        /// </summary>
        [XmlElement("buy")]
        public Boolean Buy
        {
            get { return this.m_vBuy; }
            set { this.m_vBuy = value; this.NotifyPropertyChanged("Buy"); }
        }

        /// <summary>
        /// Gets or sets the social flag of this item.
        /// </summary>
        [XmlElement("social")]
        public Boolean Social
        {
            get { return this.m_vSocial; }
            set { this.m_vSocial = value; this.NotifyPropertyChanged("Social"); }
        }

        /// <summary>
        /// Gets or sets the vanity flag of this item.
        /// </summary>
        [XmlElement("vanity")]
        public Boolean Vanity
        {
            get { return this.m_vVanity; }
            set { this.m_vVanity = value; this.NotifyPropertyChanged("Vanity"); }
        }

        /// <summary>
        /// Gets or sets the metarial flag of this item.
        /// </summary>
        [XmlElement("material")]
        public Boolean Material
        {
            get { return this.m_vMaterial; }
            set { this.m_vMaterial = value; this.NotifyPropertyChanged("Material"); }
        }

        /// <summary>
        /// Gets or sets the no wet flag of this item.
        /// </summary>
        [XmlElement("noWet")]
        public Boolean NoWet
        {
            get { return this.m_vNoWet; }
            set { this.m_vNoWet = value; this.NotifyPropertyChanged("NoWet"); }
        }

        /// <summary>
        /// Gets or sets the buff type of this item.
        /// </summary>
        [XmlElement("buffType")]
        public Int32 BuffType
        {
            get { return this.m_vBuffType; }
            set { this.m_vBuffType = value; this.NotifyPropertyChanged("BuffType"); }
        }

        /// <summary>
        /// Gets or sets the buff time of this item.
        /// </summary>
        [XmlElement("buffTime")]
        public Int32 BuffTime
        {
            get { return this.m_vBuffTime; }
            set { this.m_vBuffTime = value; this.NotifyPropertyChanged("BuffTime"); }
        }

        /// <summary>
        /// Gets or sets the net id of this item.
        /// </summary>
        [XmlElement("netID")]
        public Int32 NetID
        {
            get { return this.m_vNetID; }
            set { this.m_vNetID = value; this.NotifyPropertyChanged("NetID"); }
        }

        /// <summary>
        /// Gets or sets the crit of this item.
        /// </summary>
        [XmlElement("crit")]
        public Int32 Crit
        {
            get { return this.m_vCrit; }
            set { this.m_vCrit = value; this.NotifyPropertyChanged("Crit"); }
        }

        /// <summary>
        /// Gets or sets the prefix of this item.
        /// </summary>
        [XmlElement("prefix")]
        public Byte Prefix
        {
            get { return this.m_vPrefix; }
            set { this.m_vPrefix = value; this.NotifyPropertyChanged("Prefix"); }
        }

        /// <summary>
        /// Gets or sets the melee flag of this item.
        /// </summary>
        [XmlElement("melee")]
        public Boolean Melee
        {
            get { return this.m_vMelee; }
            set { this.m_vMelee = value; this.NotifyPropertyChanged("Melee"); }
        }

        /// <summary>
        /// Gets or sets the magic flag of this item.
        /// </summary>
        [XmlElement("magic")]
        public Boolean Magic
        {
            get { return this.m_vMagic; }
            set { this.m_vMagic = value; this.NotifyPropertyChanged("Magic"); }
        }

        /// <summary>
        /// Gets or sets the ranged flag of this item.
        /// </summary>
        [XmlElement("ranged")]
        public Boolean Ranged
        {
            get { return this.m_vRanged; }
            set { this.m_vRanged = value; this.NotifyPropertyChanged("Ranged"); }
        }

        /// <summary>
        /// Gets or sets the reuse delay of this item.
        /// </summary>
        [XmlElement("reuseDelay")]
        public Int32 ReuseDelay
        {
            get { return this.m_vReuseDelay; }
            set { this.m_vReuseDelay = value; this.NotifyPropertyChanged("ReuseDelay"); }
        }

        /// <summary>
        /// Gets or sets the id of this item.
        /// </summary>
        [XmlIgnore]
        public Int32 Id
        {
            get { return this.m_vId; }
            set
            {
                this.m_vId = value;
                this.Icon = new Uri(String.Format(@"{0}\Data\Items\item_{1}.png", AppDomain.CurrentDomain.BaseDirectory, value), UriKind.Absolute);
                this.NotifyPropertyChanged("Id");
            }
        }

        /// <summary>
        /// Gets or sets the icon of this item.
        /// </summary>
        [XmlIgnore]
        public Uri Icon
        {
            get { return this.m_vIcon; }
            set { this.m_vIcon = value; this.NotifyPropertyChanged("Icon"); }
        }

        /// <summary>
        /// Gets or sets the count of this item.
        /// </summary>
        [XmlIgnore]
        public Int32 Count
        {
            get { return this.m_vCount; }
            set { this.m_vCount = value; this.NotifyPropertyChanged("Count"); }
        }

        /// <summary>
        /// ToString Override
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            String strToolTip = String.Empty;
            var prefix = (from ItemPrefix ip in Terraria.Instance.Prefixes
                          where ip.Id == this.Prefix
                          select ip).SingleOrDefault();
            if (prefix.Id > 0)
                strToolTip += prefix.Prefix + " ";

            strToolTip += this.Name;

            return strToolTip;
        }

        /// <summary>
        /// ICloneable Implementation
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }
}
